package com.huahan.auth.Utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * @author dd
 */

@Slf4j
@Component
public class RedisHelper {

  @Resource
  private RedisTemplate redisTemplate;


  /**
   * 缓存Map
   *
   * @param key
   * @param dataMap
   * @return
   */
  public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
    HashOperations hashOperations = redisTemplate.opsForHash();
    if (null != dataMap) {
      for (Map.Entry<String, T> entry : dataMap.entrySet()) {
        hashOperations.put(key, entry.getKey(), entry.getValue());
      }
    }
    return hashOperations;
  }

  /**
   * 获得缓存的Map
   *
   * @param key
   * @return
   */
  public <T> Map<String, T> getCacheMap(String key) {
    Map<String, T> map = redisTemplate.opsForHash().entries(key);
    return map;
  }

    /**
     * 缓存value操作
     *
     * @param k    key
     * @param v    value
     * @param time 时间
     * @param unit 时间单位
     * @return
     */
  public boolean cacheValue(String k, Serializable v, long time, TimeUnit unit) {
    try {
      ValueOperations<String, Object> valueOps = redisTemplate.opsForValue();
      valueOps.set(k, v);
      if (time > 0) {
        redisTemplate.expire(k, time, unit);
      }
      return true;
    } catch (Throwable t) {
      log.error("缓存[{}]失败,key[" + k + ", + v + " + v + " error[" + t + "]");
    }
    return false;
  }

  /**
   * 缓存value操作
   *
   * @param k    key
   * @param v    value
   * @param time 时间
   * @return
   */
  public boolean cacheValue(String k, Serializable v, long time) {
    try {
      return cacheValue(k, v, time, TimeUnit.MINUTES);
    } catch (Throwable t) {
      log.error("缓存[{}]失败,key[" + k + ", + v + " + v + " error[" + t + "]");
    }
    return false;
  }
  /**
   * 缓存value操作
   *
   * @param k    key
   * @param v    value
   * @param time 时间
   * @return
   */
  public boolean cacheValueMINUTES(String k, Serializable v, long time) {
    try {
      return cacheValue(k, v, time, TimeUnit.MINUTES);
    } catch (Throwable t) {
      log.error("缓存[{}]失败,key[" + k + ", + v + " + v + " error[" + t + "]");
    }
    return false;
  }

  /**
   * 缓存value操作
   *
   * @param k key
   * @param v value
   * @return
   */
  public boolean cacheValue(String k, Serializable v) {
    return cacheValue(k, v, -1);
  }

  /**
   * 判断缓存是否存在
   *
   * @param k key
   * @return
   */
  public Boolean hasKey(String k) {
    try {
      return redisTemplate.hasKey(k);
    } catch (Throwable t) {
      log.error("判断缓存存在失败key[" + k + ", error[" + t + "]");
    }
    return Boolean.FALSE;
  }

  /**
   * 根据前缀获取所有的key
   * 例如：pro_*
   */
  public List<String> getPrefixAllValue(String prefix) {
    try {
        Set<String> keys = redisTemplate.keys(prefix.concat("*"));
        if(keys.isEmpty()){
          return new ArrayList<>();
        }
        List<String> collect = new ArrayList<>();
        for (String key : keys) {
          collect.add(redisTemplate.opsForValue().get(key).toString());
        }
        return collect;
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + prefix + ", error[" + t + "]");
    }
    return  new ArrayList<>();
  }
  /**
   * 根据前缀获取所有的key
   * 例如：pro_*
   */
  public List<String> getPrefixAllKey(String prefix) {
    try {
        Set<String> keys = redisTemplate.keys(prefix.concat("*"));
        if(keys.isEmpty()){
          return new ArrayList<>();
        }
        return keys.stream().collect(Collectors.toList());
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + prefix + ", error[" + t + "]");
    }
    return  new ArrayList<>();
  }

  /**
   * 递增
   *
   * @param k
   * @param delta 要增加几(大于0)
   * @return
   */
  public long increment(String k, long delta) {
    if (delta < 0) {
      throw new RuntimeException("递增因子必须大于0");
    }
    return redisTemplate.opsForValue().increment(k, delta);
  }

  /**
   * 递减
   *
   * @param k     键
   * @param delta 要减少几(小于0)
   * @return
   */
  public long decrement(String k, long delta) {
    if (delta < 0) {
      throw new RuntimeException("递减因子必须大于0");
    }
    return redisTemplate.opsForValue().increment(k, -delta);
  }

  /**
   * 获取缓存
   *
   * @param k key
   * @return
   */
  public Object getValue(String k) {
    try {
      ValueOperations<String, Object> valueOps = redisTemplate.opsForValue();
      return valueOps.get(k);
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + k + ", error[" + t + "]");
    }
    return null;
  }
  /**
   * 获取缓存
   *
   * @param k key
   * @return
   */
  public String getValueStr(String k) {
    try {
      ValueOperations<String, Object> valueOps = redisTemplate.opsForValue();
      return String.valueOf(valueOps.get(k));
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + k + ", error[" + t + "]");
    }
    return "";
  }

  public Object hashGet(String key, Object hashKey) {
    try {
      HashOperations<String, Object, Object> hashOps = redisTemplate.opsForHash();
      return hashOps.get(key, hashKey);
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + key + " hashKey " + hashKey + ", error[" + t + "]");
    }
    return null;
  }
  /**
   * 查询key的生命周期
   *
   * @param key
   * @param timeUnit
   * @return
   */
  public long getKeyExpire(String key, TimeUnit timeUnit) {
    try {
      return redisTemplate.getExpire(key, timeUnit);
    } catch (Throwable t) {
      log.error("获取缓存失败key[" + key + " hashKey " + timeUnit + ", error[" + t + "]");
    }
    return 0L;
  }
  /**
   * 删除缓存
   *
   * @param k key
   * @return
   */
  public Boolean removeValue(String k) {
    try {
      redisTemplate.expire(k, 0, TimeUnit.SECONDS);
      return Boolean.TRUE;
    } catch (Throwable t) {
      log.error("删除缓存失败key[" + k + ", error[" + t + "]");
    }
    return Boolean.FALSE;
  }

  /**
   * 删除缓存
   *
   * @param k    key
   * @param time time
   * @param unit timeUnit
   * @return
   */
  public Boolean expire(String k, long time, TimeUnit unit) {
    try {
      redisTemplate.expire(k, time, unit);
      return Boolean.TRUE;
    } catch (Throwable t) {
      log.error("设置缓存时间失败key[" + k + ", error[" + t + "]");
    }
    return Boolean.FALSE;
  }

  /**
   * 删除指定的一个数据
   *
   * @param key key值
   * @return true 删除成功，否则返回异常信息
   */
  public Boolean deleteKey(String key) {
    try {
      return redisTemplate.delete(key);
    } catch (Exception ex) {
      throw ex;
//      throw MyExceptionUtil.mxe("删除失败！", ex);
    }
  }

  /**
   * 将list放入缓存
   *
   * @param key   key的值
   * @param value 放入缓存的数据
   * @return true 代表成功，否则返回异常信息
   */
  public Boolean setList(String key, Object value) {
    try {
      redisTemplate.opsForList().rightPush(key, value);
      return true;
    } catch (Exception ex) {
      throw ex;
//        throw MyExceptionUtil.mxe("插入List缓存失败！", ex);
    }
  }


  /**
   * 将Object数据放入List缓存，并设置时间
   *
   * @param key   key值
   * @param value 数据的值
   * @param time  缓存的时间
   * @return true插入成功，否则返回异常信息
   */
  public Boolean setList(String key, Object value, long time) {
    try {
      if (time > 0) {
        redisTemplate.opsForList().rightPush(key, value);
        expire(key, time,TimeUnit.SECONDS);
        return true;
      }
      return false;
    } catch (Exception ex) {
      throw ex;
//        throw MyExceptionUtil.mxe("插入List缓存失败！", ex);
    }
  }


  /**
   * 将list集合放入List缓存，并设置时间
   *
   * @param key   key值
   * @param value 数据的值
   * @param time  缓存的时间
   * @return true插入成功，否则返回异常信息
   */
  public Boolean setListAll(String key, Object value, long time) {
    try {
      if (time > 0) {
        redisTemplate.opsForList().rightPushAll(key, value);
        this.expire(key, time,TimeUnit.SECONDS);
        return true;
      }
      return false;
    } catch (Exception ex) {
      throw ex;
//        throw MyExceptionUtil.mxe("插入List缓存失败！", ex);
    }
  }


  /**
   * 根据索引获取缓存List中的内容
   *
   * @param key   key的值
   * @param start 索引开始
   * @param end   索引结束 0 到 -1代表所有值
   * @return 返回数据
   */
  public List<Object> getList(String key, long start, long end) {
    try {
      return redisTemplate.opsForList().range(key, start, end);
    } catch (Exception ex) {
      throw ex;
//        throw MyExceptionUtil.mxe("获取缓存List中的内容失败了！", ex);
    }
  }


  /**
   * 删除List缓存中多个list数据
   *
   * @param key   key值
   * @param count 移除多少个
   * @param value 可以传null  或者传入存入的Value的值
   * @return 返回删除了多少个
   */
  public long deleteListIndex(String key, long count, Object value) {
    try {
      return redisTemplate.opsForList().remove(key, count, value);
    } catch (Exception ex) {
      throw ex;
//        throw MyExceptionUtil.mxe("删除List中的内容失败了！", ex);
    }
  }

  /**
   * 获取List缓存的数据
   *
   * @param key key值
   * @return 返回长度
   */
  public long getListSize(String key) {
    try {
      return redisTemplate.opsForList().size(key);
    } catch (Exception ex) {
      throw ex;
//      throw MyExceptionUtil.mxe("获取List长度失败", ex);
    }
  }
  /**
   *
   */





}
